package org.boulderfoodrescue.webapp.client.pickuptimes.timepicker;

import java.io.Serializable;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.boulderfoodrescue.webapp.shared.OneTimeEvent;

import com.google.gwt.i18n.client.DateTimeFormat;


public class PickupWindow implements Serializable {
	private static final long serialVersionUID = -5679908400803456057L;
	private Date start_time;
	private Date end_time;
	private boolean allDay;
	/*
	 * -1 = false
	 * 0 = daily
	 * 1 = weekday
	 * 2 = mon, wed, fri
	 * 3 = tues, thurs
	 * 4 = weekly
	 * 5 = monthly
	 * 6 = yearly
	 */
	public enum RepeatType{None, Daily, Weekly, Monthly, Yearly}
	private RepeatType repeatType = RepeatType.None;
	private int repeatInterval = 0;
	/*
	 * String representing days of the week
	 * 0 = false
	 * 1 = true
	 * index = day of week
	 * 0 = sunday 
	 * 6 = saturday
	 */
	private String repeatsOn = "0000000";
	/*
	 * 0 = day of the month
	 * 1 = day of the week
	 */
	private int repeatBy = 0;
	private Date startsOn;
	/*
	 * 0 = never
	 * 1 = after set number of occurences
	 * 2 = after date
	 */
	private int endType = 0;
	private Date endDate;
	private int numOccurances;

	public List<OneTimeEvent> generateRepeatedTimes(Date start,Date end){
		List<OneTimeEvent> list = new LinkedList<OneTimeEvent>();
		if(repeatType == RepeatType.None){
			if(start_time.getTime() > start.getTime() && start_time.getTime() < end.getTime())
				list.add(new OneTimeEvent(start_time, end_time, false));
			return list;
		}
		long event_length = end_time.getTime() - start_time.getTime();
		if(repeatType == RepeatType.Daily){
			if(start_time.getTime()>end.getTime())
				return list;
			Date current;
			if(start_time.getTime()> start.getTime())
				current = new Date(start_time.getTime());
			else
				current = new Date(start.getTime());
			while(current.getTime() < end.getTime()){
				list.add(new OneTimeEvent(current, event_length, false));
				current = new Date(current.getTime() + 1000L*60L*60L*24L);
			}
		}
		if(repeatType == RepeatType.Daily){
			if(start_time.getTime()>end.getTime())
				return list;
			Date current;
			if(start_time.getTime()> start.getTime())
				current = new Date(start_time.getTime());
			else
				current = new Date(start.getTime());
			while(current.getTime() < end.getTime()){
				list.add(new OneTimeEvent(current, event_length, false));
				current = new Date(current.getTime() + 1000L*60L*60L*24L);
			}
		}
		return list;
	}

	public PickupWindow clone(){
		PickupWindow clone = new PickupWindow();
		clone.setAllDay(this.allDay);
		if(this.end_time != null)
			clone.setEnd_time((Date) this.end_time.clone());
		if(this.endDate != null)
			clone.setEndDate((Date) this.endDate.clone());
		clone.setEndType(this.endType);
		clone.setNumOccurances(this.numOccurances);
		clone.setRepeatBy(this.repeatBy);
		clone.setRepeatInterval(this.repeatInterval);
		clone.setRepeatsOn(this.repeatsOn);
		clone.setRepeatType(this.repeatType);
		if(this.start_time != null)
			clone.setStart_time((Date) this.start_time.clone());
		if(this.startsOn != null)
			clone.setStartsOn((Date) this.startsOn.clone());
		return clone;
	}

	public String getSummary(){
		StringBuilder sb = new StringBuilder();
		if(repeatInterval != 0){
			sb.append("Every ");
			sb.append(repeatInterval+1);
			switch(repeatType){
			case Daily:
				sb.append(" Days ");
				break;
			case Weekly:
				sb.append(" Weeks ");
				break;
			case Monthly:
				sb.append(" Months ");
				break;
			case Yearly:
				sb.append(" Years ");
				break;
			}
		}
		else{
			switch(repeatType){
			case Daily:
				sb.append("Daily ");
				break;
			case Weekly:
				sb.append("Weekly ");
				break;
			case Monthly:
				sb.append("Montly ");
				break;
			case Yearly:
				sb.append("Yearly ");
				break;
			}
		}
		switch(repeatType){
		case Daily:
			sb.append("TO DO ");
			break;
		case Weekly:
			sb.append("on ");
			sb.append(getDaysOfWeek());
			sb.append(" ");
			break;
		case Monthly:
			sb.append("TO DO ");
			break;
		case Yearly:
			sb.append("TO DO ");
			break;
		}
		switch(endType){
		case 1:
			sb.append(", ");
			sb.append(numOccurances);
			sb.append(" times");
			break;
		case 2:
			sb.append(", until ");
			sb.append(DateTimeFormat.getFormat(DateTimeFormat
					.PredefinedFormat.DATE_SHORT).format(endDate));
		}
		return sb.toString();
	}

	public String getDaysOfWeek(){
		List<Boolean> days = getRepeatsOnList();
		StringBuilder sb = new StringBuilder();
		if(days.get(0))
			sb.append("Sun ");
		if(days.get(1))
			sb.append("Mon ");
		if(days.get(2))
			sb.append("Tue ");
		if(days.get(3))
			sb.append("Wed ");
		if(days.get(4))
			sb.append("Thu ");
		if(days.get(5))
			sb.append("Fri ");
		if(days.get(6))
			sb.append("Sat ");
		return sb.toString();
	}
	
	public List<Boolean> getRepeatsOnList(){
		List<Boolean> days = new LinkedList<Boolean>();
		for(int i = 0; i < repeatsOn.length(); ++i){
			if(repeatsOn.charAt(i) == '1')
				days.add(true);
			else
				days.add(false);
		}
		return days;
	}
	
	public Date getStart_time() {
		return start_time;
	}
	public void setStart_time(Date start_time) {
		this.start_time = start_time;
	}
	public Date getEnd_time() {
		return end_time;
	}
	public void setEnd_time(Date end_time) {
		this.end_time = end_time;
	}
	public boolean isAllDay() {
		return allDay;
	}

	public void setAllDay(boolean allDay) {
		this.allDay = allDay;
	}

	public RepeatType getRepeatType() {
		return repeatType;
	}
	public void setRepeatType(RepeatType repeatType) {
		this.repeatType = repeatType;
	}
	public int getRepeatInterval() {
		return repeatInterval;
	}
	public void setRepeatInterval(int repeatInterval) {
		this.repeatInterval = repeatInterval;
	}
	public String getRepeatsOn() {
		return repeatsOn;
	}
	public void setRepeatsOn(String repeatsOn) {
		this.repeatsOn = repeatsOn;
	}
	public int getRepeatBy() {
		return repeatBy;
	}
	public void setRepeatBy(int repeatBy) {
		this.repeatBy = repeatBy;
	}
	public Date getStartsOn() {
		return startsOn;
	}
	public void setStartsOn(Date startsOn) {
		this.startsOn = startsOn;
	}
	public int getEndType() {
		return endType;
	}
	public void setEndType(int endType) {
		this.endType = endType;
	}
	public Date getEndDate() {
		return endDate;
	}
	public void setEndDate(Date endDate) {
		this.endDate = endDate;
	}
	public int getNumOccurances() {
		return numOccurances;
	}
	public void setNumOccurances(int numOccurances) {
		this.numOccurances = numOccurances;
	}

	public void setRepeatTypeViaInt(int repeatType){
		switch(repeatType){
		case -1: this.repeatType = RepeatType.None; return;
		case 0: this.repeatType = RepeatType.Daily; return;
		case 1: this.repeatType = RepeatType.Weekly; return;
		case 2: this.repeatType = RepeatType.Monthly; return;
		case 3: this.repeatType = RepeatType.Yearly; return;
		}
	}

	public int getRepeatTypeAsInt() {
		/*
		 * -1 = false
		 * 0 = daily
		 * 1 = weekday
		 * 2 = mon, wed, fri
		 * 3 = tues, thurs
		 * 4 = weekly
		 * 5 = monthly
		 * 6 = yearly
		 */
		switch(repeatType){
		case None: return -1;
		case Daily: return 0;
		case Weekly: return 1;
		case Monthly: return 2;
		case Yearly: return 3;
		}
		return 0;
	}
}
